<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>声纹识别登录系统</title>
    <!-- 引入lamejs库用于MP3编码（基于libmp3lame的JavaScript实现） -->
<script src="https://unpkg.com/lamejs@1.2.1/lame.min.js"></script>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
            min-height: 100vh;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .container {
            background: white;
            border-radius: 20px;
            box-shadow: 0 20px 40px rgba(0, 0, 0, 0.1);
            padding: 40px;
            width: 100%;
            max-width: 500px;
            text-align: center;
        }

        .logo {
            font-size: 2.5em;
            color: #667eea;
            margin-bottom: 10px;
        }

        h1 {
            color: #333;
            margin-bottom: 30px;
            font-weight: 300;
        }

        .tab-container {
            display: flex;
            margin-bottom: 30px;
            border-radius: 10px;
            overflow: hidden;
            background: #f8f9fa;
        }

        .tab {
            flex: 1;
            padding: 15px;
            background: #f8f9fa;
            border: none;
            cursor: pointer;
            transition: all 0.3s ease;
            font-size: 16px;
        }

        .tab.active {
            background: #667eea;
            color: white;
        }

        .form-group {
            margin-bottom: 20px;
            text-align: left;
        }

        label {
            display: block;
            margin-bottom: 8px;
            color: #555;
            font-weight: 500;
        }

        input[type="text"], input[type="email"], input[type="password"] {
            width: 100%;
            padding: 15px;
            border: 2px solid #e1e5e9;
            border-radius: 10px;
            font-size: 16px;
            transition: border-color 0.3s ease;
        }

        input[type="text"]:focus, input[type="email"]:focus, input[type="password"]:focus {
            outline: none;
            border-color: #667eea;
        }

        .audio-section {
            background: #f8f9fa;
            border-radius: 10px;
            padding: 20px;
            margin: 20px 0;
        }

        .record-btn {
            background: #28a745;
            color: white;
            border: none;
            padding: 15px 30px;
            border-radius: 50px;
            font-size: 16px;
            cursor: pointer;
            transition: all 0.3s ease;
            margin: 10px;
        }

        .record-btn:hover {
            background: #218838;
            transform: translateY(-2px);
        }

        .record-btn.recording {
            background: #dc3545;
            animation: pulse 1s infinite;
        }

        @keyframes pulse {
            0% { transform: scale(1); }
            50% { transform: scale(1.05); }
            100% { transform: scale(1); }
        }

        .submit-btn {
            width: 100%;
            padding: 15px;
            background: #667eea;
            color: white;
            border: none;
            border-radius: 10px;
            font-size: 18px;
            cursor: pointer;
            transition: all 0.3s ease;
            margin-top: 20px;
        }

        .submit-btn:hover {
            background: #5a6fd8;
            transform: translateY(-2px);
        }

        .submit-btn:disabled {
            background: #ccc;
            cursor: not-allowed;
            transform: none;
        }

        .message {
            padding: 15px;
            border-radius: 10px;
            margin: 20px 0;
            display: none;
        }

        .message.success {
            background: #d4edda;
            color: #155724;
            border: 1px solid #c3e6cb;
        }

        .message.error {
            background: #f8d7da;
            color: #721c24;
            border: 1px solid #f5c6cb;
        }

        .audio-status {
            margin: 10px 0;
            font-size: 14px;
            color: #666;
        }

        .hidden {
            display: none;
        }

        .file-input-wrapper {
            position: relative;
            display: inline-block;
            cursor: pointer;
            background: #f8f9fa;
            border: 2px dashed #dee2e6;
            border-radius: 10px;
            padding: 20px;
            width: 100%;
            transition: all 0.3s ease;
        }

        .file-input-wrapper:hover {
            border-color: #667eea;
            background: #f0f4ff;
        }

        .file-input-wrapper input[type="file"] {
            position: absolute;
            opacity: 0;
            width: 100%;
            height: 100%;
            cursor: pointer;
        }

        .file-input-text {
            color: #666;
            font-size: 14px;
        }
    </style>
</head>
<body>
    <div class="container">
        <div class="logo">🎤</div>
        <h1>声纹识别登录系统</h1>
        
        <div class="tab-container">
            <button class="tab active" onclick="switchTab('login')">登录</button>
            <button class="tab" onclick="switchTab('register')">注册</button>
            <button class="tab" onclick="switchTab('voiceregister')">声纹注册</button>
            <button class="tab" onclick="switchTab('voiceprint')">声纹登录</button>
        </div>

        <div id="message" class="message"></div>

        <!-- 普通登录表单 -->
        <form id="loginForm" class="form-section">
            <div class="form-group">
                <label for="loginUsername">用户名</label>
                <input type="text" id="loginUsername" name="username" required>
            </div>
            <div class="form-group">
                <label for="loginPassword">密码</label>
                <input type="password" id="loginPassword" name="password" required>
            </div>
            <button type="submit" class="submit-btn">登录</button>
        </form>

        <!-- 注册表单 -->
        <form id="registerForm" class="form-section hidden">
            <div class="form-group">
                <label for="registerUsername">用户名</label>
                <input type="text" id="registerUsername" name="username" required>
            </div>
            <div class="form-group">
                <label for="registerEmail">邮箱</label>
                <input type="email" id="registerEmail" name="email" required>
            </div>
            <div class="form-group">
                <label for="registerPassword">密码</label>
                <input type="password" id="registerPassword" name="password" required>
            </div>
            <button type="submit" class="submit-btn">注册</button>
        </form>

        <!-- 声纹注册表单 -->
        <form id="voiceregisterForm" class="form-section hidden">
            <div class="form-group">
                <label for="voiceregisterUsername">用户名</label>
                <input type="text" id="voiceregisterUsername" name="username" required>
            </div>
            
            <div class="audio-section">
                <h3>录制声纹特征</h3>
                <div class="audio-status" id="voiceregisterAudioStatus">点击开始录音</div>
                <button type="button" class="record-btn" id="voiceregisterRecordBtn" onclick="toggleVoiceregisterRecording()">开始录音</button>
                <button type="button" class="record-btn" id="voiceregisterStopBtn" onclick="stopVoiceregisterRecording()" style="display: none;">停止录音</button>
                
                <div style="margin-top: 20px;">
                    <div class="file-input-wrapper">
                        <input type="file" id="voiceregisterAudioFile" accept="audio/*" onchange="handleVoiceregisterFileSelect(this)">
                        <div class="file-input-text">或者点击上传音频文件</div>
                    </div>
                </div>
            </div>
            
            <button type="submit" class="submit-btn" id="voiceregisterSubmit" disabled>注册声纹特征</button>
        </form>

        <!-- 声纹登录表单 -->
        <form id="voiceprintForm" class="form-section hidden">
            <div class="form-group">
                <label for="voiceprintUsername">用户名</label>
                <input type="text" id="voiceprintUsername" name="username" required>
            </div>
            
            <div class="audio-section">
                <h3>录制声纹</h3>
                <div class="audio-status" id="audioStatus">点击开始录音</div>
                <button type="button" class="record-btn" id="recordBtn" onclick="toggleRecording()">开始录音</button>
                <button type="button" class="record-btn" id="stopBtn" onclick="stopRecording()" style="display: none;">停止录音</button>
                
                <div style="margin-top: 20px;">
                    <div class="file-input-wrapper">
                        <input type="file" id="audioFile" accept="audio/*" onchange="handleFileSelect(this)">
                        <div class="file-input-text">或者点击上传音频文件</div>
                    </div>
                </div>
            </div>
            
            <button type="submit" class="submit-btn" id="voiceprintSubmit" disabled>声纹登录</button>
        </form>
    </div>

    <script>
        let mediaRecorder;
        let audioChunks = [];
        let recordedAudioBlob;
        let isRecording = false;

        // 切换标签页
        function switchTab(tabName) {
            // 更新标签样式
            document.querySelectorAll('.tab').forEach(tab => tab.classList.remove('active'));
            event.target.classList.add('active');

            // 隐藏所有表单
            document.querySelectorAll('.form-section').forEach(form => form.classList.add('hidden'));

            // 显示对应表单
            if (tabName === 'login') {
                document.getElementById('loginForm').classList.remove('hidden');
            } else if (tabName === 'register') {
                document.getElementById('registerForm').classList.remove('hidden');
            } else if (tabName === 'voiceregister') {
                document.getElementById('voiceregisterForm').classList.remove('hidden');
            } else if (tabName === 'voiceprint') {
                document.getElementById('voiceprintForm').classList.remove('hidden');
            }

            // 清除消息
            hideMessage();
        }

        // 声纹注册相关变量
        let voiceregisterMediaRecorder;
        let voiceregisterAudioChunks = [];
        let voiceregisterRecordedAudioBlob;
        let voiceregisterIsRecording = false;

        // 开始/停止声纹注册录音
        async function toggleVoiceregisterRecording() {
            if (!voiceregisterIsRecording) {
                await startVoiceregisterRecording();
            } else {
                stopVoiceregisterRecording();
            }
        }

        // 开始声纹注册录音
        async function startVoiceregisterRecording() {
            try {
                const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
                voiceregisterMediaRecorder = new MediaRecorder(stream);
                voiceregisterAudioChunks = [];

                voiceregisterMediaRecorder.ondataavailable = event => {
                    voiceregisterAudioChunks.push(event.data);
                };

                voiceregisterMediaRecorder.onstop = () => {
                    // 将录制的音频转换为MP3格式（16k采样率、16bit位深、单声道）
                    const audioBlob = new Blob(voiceregisterAudioChunks, { type: voiceregisterMediaRecorder.mimeType });
                    convertToMp3(audioBlob).then(mp3Blob => {
                        voiceregisterRecordedAudioBlob = mp3Blob;
                        document.getElementById('voiceregisterSubmit').disabled = false;
                        document.getElementById('voiceregisterAudioStatus').textContent = '录音完成，可以提交注册';
                    }).catch(error => {
                        console.error('音频转换失败:', error);
                        voiceregisterRecordedAudioBlob = audioBlob; // 回退到原始格式
                        document.getElementById('voiceregisterSubmit').disabled = false;
                        document.getElementById('voiceregisterAudioStatus').textContent = '录音完成，可以提交注册';
                    });
                };

                voiceregisterMediaRecorder.start();
                voiceregisterIsRecording = true;

                document.getElementById('voiceregisterRecordBtn').style.display = 'none';
                document.getElementById('voiceregisterStopBtn').style.display = 'inline-block';
                document.getElementById('voiceregisterStopBtn').classList.add('recording');
                document.getElementById('voiceregisterAudioStatus').textContent = '正在录音中...';
            } catch (error) {
                showMessage('无法访问麦克风，请检查权限设置', 'error');
            }
        }

        // 停止声纹注册录音
        function stopVoiceregisterRecording() {
            if (voiceregisterMediaRecorder && voiceregisterIsRecording) {
                voiceregisterMediaRecorder.stop();
                voiceregisterMediaRecorder.stream.getTracks().forEach(track => track.stop());
                voiceregisterIsRecording = false;

                document.getElementById('voiceregisterRecordBtn').style.display = 'inline-block';
                document.getElementById('voiceregisterStopBtn').style.display = 'none';
                document.getElementById('voiceregisterStopBtn').classList.remove('recording');
            }
        }

        // 处理声纹注册文件选择
        function handleVoiceregisterFileSelect(input) {
            if (input.files && input.files[0]) {
                voiceregisterRecordedAudioBlob = input.files[0];
                document.getElementById('voiceregisterSubmit').disabled = false;
                document.getElementById('voiceregisterAudioStatus').textContent = '音频文件已选择，可以提交注册';
            }
        }

        // 显示消息
        function showMessage(text, type = 'success') {
            const messageEl = document.getElementById('message');
            messageEl.textContent = text;
            messageEl.className = `message ${type}`;
            messageEl.style.display = 'block';
        }

        // 隐藏消息
        function hideMessage() {
            document.getElementById('message').style.display = 'none';
        }

        // 音频格式转换函数 - 转换为MP3格式（16k采样率、16bit位深、单声道）
        async function convertToMp3(audioBlob) {
            return new Promise((resolve, reject) => {
                const audioContext = new (window.AudioContext || window.webkitAudioContext)();
                const reader = new FileReader();
                
                reader.onload = function(e) {
                    audioContext.decodeAudioData(e.target.result)
                        .then(audioBuffer => {
                            // 重采样到16kHz单声道
                            const resampledBuffer = resampleAudioBuffer(audioBuffer, 16000, 1);
                            // 使用lamejs编码为真正的MP3格式
                            const mp3ArrayBuffer = encodeToMp3(resampledBuffer);
                            // 创建MP3格式的Blob
                            const mp3Blob = new Blob([mp3ArrayBuffer], { type: 'audio/mp3' });
                            resolve(mp3Blob);
                        })
                        .catch(error => {
                            console.error('音频解码失败:', error);
                            // 如果转换失败，直接返回原始音频
                            resolve(audioBlob);
                        });
                };
                
                reader.onerror = () => {
                    // 如果读取失败，直接返回原始音频
                    resolve(audioBlob);
                };
                reader.readAsArrayBuffer(audioBlob);
            });
        }

        // 重采样音频缓冲区到指定采样率和声道数
        function resampleAudioBuffer(audioBuffer, targetSampleRate, targetChannels) {
            const sourceSampleRate = audioBuffer.sampleRate;
            const sourceChannels = audioBuffer.numberOfChannels;
            
            // 如果已经是目标格式，直接返回
            if (sourceSampleRate === targetSampleRate && sourceChannels === targetChannels) {
                return audioBuffer;
            }
            
            const audioContext = new (window.AudioContext || window.webkitAudioContext)();
            const ratio = sourceSampleRate / targetSampleRate;
            const targetLength = Math.round(audioBuffer.length / ratio);
            
            // 创建新的音频缓冲区
            const resampledBuffer = audioContext.createBuffer(targetChannels, targetLength, targetSampleRate);
            
            // 处理声道转换和重采样
            for (let channel = 0; channel < targetChannels; channel++) {
                const sourceChannelData = audioBuffer.getChannelData(Math.min(channel, sourceChannels - 1));
                const targetChannelData = resampledBuffer.getChannelData(channel);
                
                // 简单的线性插值重采样
                for (let i = 0; i < targetLength; i++) {
                    const sourceIndex = i * ratio;
                    const index = Math.floor(sourceIndex);
                    const fraction = sourceIndex - index;
                    
                    if (index + 1 < sourceChannelData.length) {
                        targetChannelData[i] = sourceChannelData[index] * (1 - fraction) + sourceChannelData[index + 1] * fraction;
                    } else {
                        targetChannelData[i] = sourceChannelData[index] || 0;
                    }
                }
            }
            
            return resampledBuffer;
        }

        // 使用libmp3lame将AudioBuffer编码为MP3格式
        function encodeToMp3(audioBuffer) {
            console.log('开始转换音频为MP3格式');
            console.log('输入音频参数:', {
                sampleRate: audioBuffer.sampleRate,
                channels: audioBuffer.numberOfChannels,
                length: audioBuffer.length,
                duration: audioBuffer.duration
            });
            
            // 先重采样到16000Hz（讯飞API要求）
            const targetSampleRate = 16000;
            let processedBuffer;
            
            if (audioBuffer.sampleRate !== targetSampleRate) {
                console.log('需要重采样从', audioBuffer.sampleRate, 'Hz到', targetSampleRate, 'Hz');
                processedBuffer = resampleAudioBuffer(audioBuffer, targetSampleRate);
            } else {
                processedBuffer = audioBuffer;
            }
            
            const channelData = processedBuffer.getChannelData(0);
            const samples = new Int16Array(channelData.length);
            
            // 将Float32Array转换为Int16Array
            for (let i = 0; i < channelData.length; i++) {
                samples[i] = Math.max(-32768, Math.min(32767, Math.round(channelData[i] * 32767)));
            }
            
            // 使用lamejs编码器（基于libmp3lame）- 固定16000Hz采样率
            console.log('创建MP3编码器，采样率:', targetSampleRate);
            const mp3encoder = new lamejs.Mp3Encoder(1, targetSampleRate, 40); // 单声道，16000Hz，40kbps比特率
            const mp3Data = [];
            
            // 分块编码
            const blockSize = 1152;
            for (let i = 0; i < samples.length; i += blockSize) {
                const sampleChunk = samples.subarray(i, i + blockSize);
                const mp3buf = mp3encoder.encodeBuffer(sampleChunk);
                if (mp3buf.length > 0) {
                    mp3Data.push(mp3buf);
                }
            }
            
            // 完成编码
            const mp3buf = mp3encoder.flush();
            if (mp3buf.length > 0) {
                mp3Data.push(mp3buf);
            }
            
            // 合并所有MP3数据
            const totalLength = mp3Data.reduce((acc, chunk) => acc + chunk.length, 0);
            const result = new Uint8Array(totalLength);
            let offset = 0;
            for (const chunk of mp3Data) {
                result.set(chunk, offset);
                offset += chunk.length;
            }
            
            console.log('MP3转换完成，数据大小:', result.length, 'bytes');
            return result.buffer;
        }

        // 开始/停止录音
        async function toggleRecording() {
            if (!isRecording) {
                await startRecording();
            } else {
                stopRecording();
            }
        }

        // 开始录音
        async function startRecording() {
            try {
                const stream = await navigator.mediaDevices.getUserMedia({ audio: true });
                mediaRecorder = new MediaRecorder(stream);
                audioChunks = [];

                mediaRecorder.ondataavailable = event => {
                    audioChunks.push(event.data);
                };

                mediaRecorder.onstop = () => {
                    // 将录制的音频转换为MP3格式（16k采样率、16bit位深、单声道）
                    const audioBlob = new Blob(audioChunks, { type: mediaRecorder.mimeType });
                    convertToMp3(audioBlob).then(mp3Blob => {
                        recordedAudioBlob = mp3Blob;
                        document.getElementById('voiceprintSubmit').disabled = false;
                        document.getElementById('audioStatus').textContent = '录音完成，可以提交登录';
                    }).catch(error => {
                        console.error('音频转换失败:', error);
                        recordedAudioBlob = audioBlob; // 回退到原始格式
                        document.getElementById('voiceprintSubmit').disabled = false;
                        document.getElementById('audioStatus').textContent = '录音完成，可以提交登录';
                    });
                };

                mediaRecorder.start();
                isRecording = true;

                document.getElementById('recordBtn').style.display = 'none';
                document.getElementById('stopBtn').style.display = 'inline-block';
                document.getElementById('stopBtn').classList.add('recording');
                document.getElementById('audioStatus').textContent = '正在录音中...';
            } catch (error) {
                showMessage('无法访问麦克风，请检查权限设置', 'error');
            }
        }

        // 停止录音
        function stopRecording() {
            if (mediaRecorder && isRecording) {
                mediaRecorder.stop();
                mediaRecorder.stream.getTracks().forEach(track => track.stop());
                isRecording = false;

                document.getElementById('recordBtn').style.display = 'inline-block';
                document.getElementById('stopBtn').style.display = 'none';
                document.getElementById('stopBtn').classList.remove('recording');
            }
        }

        // 处理文件选择
        function handleFileSelect(input) {
            if (input.files && input.files[0]) {
                recordedAudioBlob = input.files[0];
                document.getElementById('voiceprintSubmit').disabled = false;
                document.getElementById('audioStatus').textContent = '音频文件已选择，可以提交登录';
            }
        }

        // 表单提交处理
        document.getElementById('loginForm').addEventListener('submit', async (e) => {
            // 防御性编程：确保事件对象存在
            if (e && typeof e.preventDefault === 'function') {
                e.preventDefault();
            }
            
            // 防御性编程：确保事件对象和target存在
            const form = (e && e.target) ? e.target : document.getElementById('loginForm');
            const formData = new FormData(form);
            const data = {
                username: formData.get('username'),
                password: formData.get('password'),
                loginType: 'PASSWORD'
            };

            try {
                console.log('发送登录请求:', data);
                const response = await fetch('/api/auth/login', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(data)
                });

                console.log('收到登录响应，状态码:', response.status);
                
                // 无论HTTP状态码是什么，都尝试解析JSON响应
                let result;
                try {
                    result = await response.json();
                    console.log('解析的登录响应数据:', result);
                } catch (parseError) {
                    console.error('登录JSON解析失败:', parseError);
                    console.error('登录响应状态:', response.status, response.statusText);
                    showMessage('服务器响应格式错误', 'error');
                    return;
                }

                // 检查业务逻辑成功标志
                if (result && result.success) {
                    showMessage('登录成功！', 'success');
                    // 这里可以跳转到主页面
                } else {
                    // 显示具体的错误信息
                    const errorMessage = result && result.message ? result.message : '登录失败';
                    showMessage(errorMessage, 'error');
                    console.log('登录失败详情:', result);
                }
            } catch (error) {
                console.error('登录请求失败:', error);
                console.error('登录错误类型:', error && error.name ? error.name : 'Unknown');
                console.error('登录错误信息:', error && error.message ? error.message : 'Unknown error');
                showMessage('网络错误，请稍后重试', 'error');
            }
        });

        document.getElementById('registerForm').addEventListener('submit', async (e) => {
            // 防御性编程：确保事件对象存在
            if (e && typeof e.preventDefault === 'function') {
                e.preventDefault();
            }
            
            // 防御性编程：确保事件对象和target存在
            const form = (e && e.target) ? e.target : document.getElementById('registerForm');
            const formData = new FormData(form);
            const data = {
                username: formData.get('username'),
                email: formData.get('email'),
                password: formData.get('password')
            };

            try {
                console.log('发送注册请求:', data);
                const response = await fetch('/api/auth/register', {
                    method: 'POST',
                    headers: {
                        'Content-Type': 'application/json'
                    },
                    body: JSON.stringify(data)
                });

                console.log('收到响应，状态码:', response.status);
                
                // 无论HTTP状态码是什么，都尝试解析JSON响应
                let result;
                try {
                    result = await response.json();
                    console.log('解析的响应数据:', result);
                } catch (parseError) {
                    console.error('JSON解析失败:', parseError);
                    console.error('响应状态:', response.status, response.statusText);
                    showMessage('服务器响应格式错误', 'error');
                    return;
                }

                // 检查业务逻辑成功标志
                if (result && result.success) {
                    showMessage('注册成功！请登录', 'success');
                    switchTab('login');
                } else {
                    // 显示具体的错误信息
                    const errorMessage = result && result.message ? result.message : '注册失败';
                    showMessage(errorMessage, 'error');
                    console.log('注册失败详情:', result);
                }
            } catch (error) {
                showMessage('注册成功！请登录', 'success');
                switchTab('login');
            }
        });

        document.getElementById('voiceregisterForm').addEventListener('submit', async (e) => {
            // 防御性编程：确保事件对象存在
            if (e && typeof e.preventDefault === 'function') {
                e.preventDefault();
            }
            
            if (!voiceregisterRecordedAudioBlob) {
                showMessage('请先录制音频或上传音频文件', 'error');
                return;
            }

            const formData = new FormData();
            formData.append('username', document.getElementById('voiceregisterUsername').value);
            formData.append('audioFile', voiceregisterRecordedAudioBlob, 'voice.mp3');

            try {
                console.log('发送声纹注册请求，用户名:', document.getElementById('voiceregisterUsername').value);
                const response = await fetch('/api/auth/voiceprint-register', {
                    method: 'POST',
                    body: formData
                });

                console.log('收到声纹注册响应，状态码:', response.status);
                
                // 无论HTTP状态码是什么，都尝试解析JSON响应
                let result;
                try {
                    result = await response.json();
                    console.log('解析的声纹注册响应数据:', result);
                } catch (parseError) {
                    console.error('声纹注册JSON解析失败:', parseError);
                    console.error('声纹注册响应状态:', response.status, response.statusText);
                    showMessage('服务器响应格式错误', 'error');
                    return;
                }

                // 检查业务逻辑成功标志
                if (result && result.success) {
                    showMessage('声纹注册成功！', 'success');
                    // 可以切换到登录页面
                } else {
                    // 显示具体的错误信息
                    const errorMessage = result && result.message ? result.message : '声纹注册失败';
                    showMessage(errorMessage, 'error');
                    console.log('声纹注册失败详情:', result);
                }
            } catch (error) {
                console.error('声纹注册请求失败:', error);
                console.error('声纹注册错误类型:', error && error.name ? error.name : 'Unknown');
                console.error('声纹注册错误信息:', error && error.message ? error.message : 'Unknown error');
                showMessage('网络错误，请稍后重试', 'error');
            }
        });

        document.getElementById('voiceprintForm').addEventListener('submit', async (e) => {
            // 防御性编程：确保事件对象存在
            if (e && typeof e.preventDefault === 'function') {
                e.preventDefault();
            }
            
            if (!recordedAudioBlob) {
                showMessage('请先录制音频或上传音频文件', 'error');
                return;
            }

            const formData = new FormData();
            formData.append('username', document.getElementById('voiceprintUsername').value);
            formData.append('audioFile', recordedAudioBlob, 'voice.mp3');

            try {
                console.log('发送声纹登录请求，用户名:', document.getElementById('voiceprintUsername').value);
                const response = await fetch('/api/auth/voiceprint-login', {
                    method: 'POST',
                    body: formData
                });

                console.log('收到声纹登录响应，状态码:', response.status);
                
                // 无论HTTP状态码是什么，都尝试解析JSON响应
                let result;
                try {
                    result = await response.json();
                    console.log('解析的声纹登录响应数据:', result);
                } catch (parseError) {
                    console.error('声纹登录JSON解析失败:', parseError);
                    console.error('声纹登录响应状态:', response.status, response.statusText);
                    showMessage('服务器响应格式错误', 'error');
                    return;
                }

                // 检查业务逻辑成功标志
                if (result && result.success) {
                    showMessage('声纹登录成功！', 'success');
                    // 保存用户信息并跳转到管理界面
                    const username = document.getElementById('voiceprintUsername').value;
                    localStorage.setItem('currentUser', username);
                    localStorage.setItem('loginTime', new Date().toISOString());
                    setTimeout(() => {
                        window.location.href = 'admin.html?user=' + encodeURIComponent(username);
                    }, 1500);
                } else {
                    // 显示具体的错误信息
                    const errorMessage = result && result.message ? result.message : '声纹登录失败';
                    showMessage(errorMessage, 'error');
                    console.log('声纹登录失败详情:', result);
                }
            } catch (error) {
                console.error('声纹登录请求失败:', error);
                console.error('声纹登录错误类型:', error && error.name ? error.name : 'Unknown');
                console.error('声纹登录错误信息:', error && error.message ? error.message : 'Unknown error');
                showMessage('网络错误，请稍后重试', 'error');
            }
        });
    </script>
</body>
</html>